//
// Created by twetec on 25-7-30.
//

#include "handle_telnet_backup_task.h"

#include <gotelnet/gotelnet.h>

using namespace std::chrono_literals;

namespace network_prober::backup
{
TELNETBackupIPv4::TELNETBackupIPv4(
    std::string_view interface,
    std::string_view target,
    std::string_view command,
    std::string_view account,
    std::string_view password,
    std::string_view privilegedPassword,
    std::uint32_t port
)
: m_interface(interface), m_target(target), m_command(command), m_account(account), m_password(password),
m_privilegedPassword(privilegedPassword), m_port(port)
{

}

void TELNETBackupIPv4::setOnBackupedCallback(std::function<void(std::string_view)> callback)
{
    m_onBackupedCallback = std::move(callback);
}

void TELNETBackupIPv4::backup()
{
    // 指向当前对象的shared_ptr
    auto self{shared_from_this()};

    // 发起探测
    m_onBackupedCallbackFuture = std::async(std::launch::async, [this, self] {
        // 备份数据
        const char* backupData = nullptr;

        // 尝试3次备份，第一次
        for (std::size_t i = 0; i < 3; i ++) {
            // 尝试备份
            backupData = TelnetGetConfig(
                const_cast<char*>(m_target.c_str()),
                const_cast<char*>(m_account.c_str()),
                const_cast<char*>(m_password.c_str()),
                const_cast<char*>(m_privilegedPassword.c_str()),
                const_cast<char*>(m_command.c_str()),
                const_cast<char*>(m_interface.c_str()),
                m_port,
                60  // 超时时间 秒
            );
            // 暂停
            std::this_thread::sleep_for(60s);
        }

        // 回调结果
        m_onBackupedCallback(backupData == nullptr? "" : backupData);
    });
}

TELNETBackupIPv4::~TELNETBackupIPv4()
{

}

HandleTELNETBackupIPv4Awaiter::HandleTELNETBackupIPv4Awaiter(const database::BackupTaskModel &backupTask)
: m_interface(backupTask.interface), m_target(backupTask.address), m_command(backupTask.command),
m_account(backupTask.account), m_password(backupTask.password),
m_privilegedPassword(backupTask.privilegedPassword), m_port(backupTask.port)
{

}

bool HandleTELNETBackupIPv4Awaiter::await_ready()
{
    return false;
}

void HandleTELNETBackupIPv4Awaiter::await_suspend(std::coroutine_handle<> handle)
{
    // 保存协程控制对象
    m_coroutineHandle = handle;

    // 创建观测对象
    std::shared_ptr<TELNETBackupIPv4> probePtr = std::make_shared<TELNETBackupIPv4>(
        m_interface, m_target, m_command, m_account, m_password, m_privilegedPassword, m_port
    );

    // 设定观测结果回调
    probePtr->setOnBackupedCallback([this](std::string_view backupData) {
        // 保存观测延迟
        m_backupData = backupData;
        // 继续执行
        m_coroutineHandle.resume();
    });

    // 启动备份
    probePtr->backup();
}

std::string HandleTELNETBackupIPv4Awaiter::await_resume()
{
    return m_backupData;
}


TELNETBackupIPv6::TELNETBackupIPv6(
    std::string_view interface,
    std::string_view target,
    std::string_view command,
    std::string_view account,
    std::string_view password,
    std::string_view privilegedPassword,
    std::uint32_t port
)
: m_interface(interface), m_target(target), m_command(command), m_account(account), m_password(password),
m_privilegedPassword(privilegedPassword), m_port(port)
{

}

void TELNETBackupIPv6::setOnBackupedCallback(std::function<void(std::string_view)> callback)
{
    m_onBackupedCallback = std::move(callback);
}

void TELNETBackupIPv6::backup()
{
    // 指向当前对象的shared_ptr
    auto self{shared_from_this()};

    // 发起探测
    m_onBackupedCallbackFuture = std::async(std::launch::async, [this, self] {
        // 备份数据
        const char* backupData = nullptr;

        // 尝试2次备份，第一次
        for (std::size_t i = 0; i < 2; i ++) {
            // 尝试备份
            backupData = TelnetGetConfig(
                const_cast<char*>(m_target.c_str()),
                const_cast<char*>(m_account.c_str()),
                const_cast<char*>(m_password.c_str()),
                const_cast<char*>(m_privilegedPassword.c_str()),
                const_cast<char*>(m_command.c_str()),
                const_cast<char*>(m_interface.c_str()),
                m_port,
                60  // 超时时间 秒
            );
            // 暂停10秒
            std::this_thread::sleep_for(60s);
        }

        // 回调结果
        m_onBackupedCallback(backupData == nullptr? "" : backupData);
    });
}

TELNETBackupIPv6::~TELNETBackupIPv6()
{
}

HandleTELNETBackupIPv6Awaiter::HandleTELNETBackupIPv6Awaiter(const database::BackupTaskModel &backupTask)
: m_interface(backupTask.interface), m_target(backupTask.address), m_command(backupTask.command),
m_account(backupTask.account), m_password(backupTask.password),
m_privilegedPassword(backupTask.privilegedPassword), m_port(backupTask.port)
{

}

bool HandleTELNETBackupIPv6Awaiter::await_ready()
{
    return false;
}

void HandleTELNETBackupIPv6Awaiter::await_suspend(std::coroutine_handle<> handle)
{
    // 保存协程控制对象
    m_coroutineHandle = handle;

    // 创建观测对象
    std::shared_ptr<TELNETBackupIPv6> probePtr = std::make_shared<TELNETBackupIPv6>(
        m_interface, m_target, m_command, m_account, m_password, m_privilegedPassword, m_port
    );

    // 设定观测结果回调
    probePtr->setOnBackupedCallback([this](std::string_view backupData) {
        // 保存观测延迟
        m_backupData = backupData;
        // 继续执行
        m_coroutineHandle.resume();
    });

    // 启动备份
    probePtr->backup();
}

std::string HandleTELNETBackupIPv6Awaiter::await_resume()
{
    return m_backupData;
}
}